#include "stdafx.h"
#include "Solver.h"

DictionaryTree * Dictionary;
Solver * pSolve;


bool operator<(const Word& a, const Word& b) {
    return a.points < b.points;
}


//int valuearray[26] =	{ 1, 4, 3, 2, 1, 5, 3, 4, 2, 8, 5, 3, 4, 2, 1, 3, 10, 2, 1, 1, 3, 5, 4, 8, 4, 10 };	//Puzzle word		

					 // { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,  R, S, T, U, V, W, X, Y, Z }


int valuearray[26] =    { 1, 3, 3, 2, 1, 4, 2, 4, 3, 8, 5, 5, 3, 2, 1, 3, 10, 1, 1, 1, 2, 4, 4, 8, 4, 10 };
int pointarray[26] =	{ 1, 3, 3, 2, 1, 4, 2, 4, 3, 8, 5, 5, 3, 2, 1, 3, 10, 1, 1, 1, 2, 4, 4, 8, 4, 10 }; //Word Soup

					 // { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q,  R, S, T, U, V, W, X, Y, Z }
//int valuearray[26] =	{ 1, 4, 3, 2, 1, 5, 3, 4, 2, 8, 5, 3, 4, 2, 1, 3, 10, 2, 1, 1, 3, 5, 4, 8, 4, 10 };	//Puzzle word		
//int pointarray[26] =	{ 1, 3, 3, 2, 1, 4, 2, 4, 3, 8, 5, 5, 3, 2, 1, 3, 10, 1, 1, 1, 2, 4, 4, 8, 4, 10 }; //Word Soup

int GetPoints(char letter)//, bool false)
{
	if (letter >= 'A' && letter <= 'Z') return pointarray[letter - 'A'];

	return 0;
}

int GetPointsValue(char letter)//, bool false)
{
	if (letter >= 'A' && letter <= 'Z') return valuearray[letter - 'A'];

	return 0;
}

void VRecurse(Grid * in);


void Length(Grid * in)
{
	if (in->length > in->mostvalue)
	{
		in->mostvalue = in->length;

		for (int c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}


void ScoreConstraint(Grid * in)
{

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	if (points > in->mostvalue)
	{
		Grid * newgrid = new Grid(in);

		newgrid->ApplyWord(in->current, in->length);
		newgrid->FallGrid();

		//float grad = newgrid->Gradient();

		delete newgrid;

		//if (grad < 0.25) return;

		in->mostvalue = points;

		for (int c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}


void BestScore(Grid * in)
{
	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		for (int c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}



void MostWords(Grid * in)
{
	Grid * newgrid = new Grid(in);

	newgrid->pCallBack = (CallBack)0;

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();
	
	newgrid->FindWords();

	int words = newgrid->words;
	delete newgrid;

	if (words > in->mostvalue)
	{
		in->mostvalue = words;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}

void Iterate(Grid * in)
{

	Grid * newgrid = new Grid(in);

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	newgrid->pCallBack = (CallBack)BestScore;

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();
	
	newgrid->FindWords();

	points += newgrid->mostvalue;

	delete newgrid;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}

	/*in->words++;

	int points = 0;//GetPoints(in->grid[x][y]);
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	if (points > in->mostvalue)
	{
		//printf("Word: ");
		//int c=0;
		//for (c=0;c<length;c++)
		//	printf("%c", current[c].letter);
		//printf("%c = %d\n", grid[x][y], points);

		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}*/

}

void DepthFirst(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();

//	newgrid->PrintGrid();

	if (newgrid->grid[COLS-1][ROWS-1] == 0)
	{
		points += 500;
	}
	else {
		newgrid->pCallBack = (CallBack)DepthFirst;
		newgrid->FindWords();

		if (newgrid->words)
		{
			points += newgrid->mostvalue;
		}
	}
	
	delete newgrid;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}

void Recurse(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();
	
	points += BSolve(newgrid);

	delete newgrid;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}



int BSolve(Grid * grid)
{
	grid->pCallBack = (CallBack)BestScore;

	int allpoints = 0;

	while(1)
	{
		if (grid->grid[COLS-1][ROWS-1] == 0) return (allpoints + 500);

		grid->FindWords();

		if (!grid->words)
			return allpoints;

		int points = 0;
		for (int b=0;b<grid->wordlen;b++)
			points += GetPoints(grid->word[b].letter);

		allpoints += points * (grid->wordlen);
		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();
	}
}

int SolveNew(Grid * in)
{
	Grid * gridnext,* grid = in;

	int allpoints = 0;

	while(1)
	{
		if (grid->grid[COLS-1][ROWS-1] == 0) return (allpoints + 500);

		grid->pCallBack = (CallBack)BestScore;
		grid->FindWords();

		if (!grid->words)
			return allpoints;

		int points = 0;
		for (int b=0;b<grid->wordlen;b++)
			points += GetPoints(grid->word[b].letter);

		allpoints += points * (grid->wordlen);

		gridnext = new Grid(grid);

		gridnext->ApplyWord(grid->word, grid->wordlen);
		gridnext->FallGrid();

		grid->next = gridnext;
		grid = gridnext;
	}
}


int LSolve(Grid * grid)
{
	grid->pCallBack = (CallBack)Length;

	int allpoints = 0;

	while(1)
	{
		if (grid->grid[COLS-1][ROWS-1] == 0) return (allpoints + 500);

		grid->FindWords();

		if (!grid->words)
			return allpoints;

		/*int points = 0;
		for (int b=0;b<grid->wordlen;b++)
			points += GetPoints(grid->word[b].letter);
			*/

		allpoints += grid->wordlen;

		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();
	}
}


void LRecurse(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int points = 0;
	/*for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}*/

	points = in->length;

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();
	
	points += LSolve(newgrid);

	delete newgrid;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}

void SolveTree(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();

//	newgrid->PrintGrid();

	if (newgrid->grid[COLS-1][ROWS-1] == 0)
	{
		points += 500;
	}
	else {
		newgrid->pCallBack = (CallBack)SolveTree;
		newgrid->FindWords();

		if (newgrid->words)
		{
			points += newgrid->mostvalue;
		}
	}
	
	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		Grid * del;//= in->next;
		while (in->next)
		{
			del = in->next;
			in->next = del->next;

			delete (del);
		}

		in->next = newgrid;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
	else {
		Grid * del;//= in->next;
		while (newgrid)
		{
			del = newgrid;
			newgrid = del->next;

			delete (del);
		}
	}
}

void SolveTest(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();

	points += SolveNew(newgrid);

//	newgrid->PrintGrid();

	/*
	if (newgrid->grid[COLS-1][ROWS-1] == 0)
	{
		points += 500;
	}
	else {
		newgrid->pCallBack = (CallBack)SolveTree;
		newgrid->FindWords();

		if (newgrid->words)
		{
			points += newgrid->mostvalue;
		}
	}*/
	
	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		Grid * del;//= in->next;
		while (in->next)
		{
			del = in->next;
			in->next = del->next;

			delete (del);
		}

		in->next = newgrid;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
	else {
		Grid * del;//= in->next;
		while (newgrid)
		{
			del = newgrid;
			newgrid = del->next;

			delete (del);
		}
	}
}


#define MAXWORDS 10



void BestScores(Grid * in)
{
	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);
	}

	points = points * (in->length);

	if (in->wordlist.size() == MAXWORDS && in->wordlist[MAXWORDS-1]->points > points)
		return;

	Word * newword = new Word();
	
	newword->length = in->length;
	newword->points = points;
	for (int c=0;c<in->length;c++)
	{
		newword->word[c].letter = in->current[c].letter;
		newword->word[c].x = in->current[c].x;
		newword->word[c].y = in->current[c].y;
	}

	for (std::vector<Word*>::iterator it = in->wordlist.begin(); it!=in->wordlist.end(); ++it) {

		if ((*it)->points < points)
		{
			in->wordlist.insert(it, newword);
			
			if (in->wordlist.size() > MAXWORDS)
			{
				delete in->wordlist[MAXWORDS-1];
				in->wordlist.erase(in->wordlist.end());
			}

			return;
		}
	}

	delete newword;
}


int SolverThing(Grid * grid, int depth)
{
	grid->mostvalue = 0;

	Grid * newgrid = 0;
	
	grid->pCallBack = BestScores;
	grid->FindWords();

	if (!grid->words)
	{
		if (grid->grid[COLS-1][ROWS-1] == 0)
			grid->mostvalue = 500;
		else 
			grid->mostvalue = 0;

		return -1;
	}

	if (!depth)
		return 0;

	int bestword = -1;

	for (int g=0;g<(int)grid->wordlist.size();g++)
	{
		newgrid = new Grid(grid);
		newgrid->ApplyWord(grid->wordlist[g]->word, grid->wordlist[g]->length);
		newgrid->FallGrid();

		//int word = SolverThing(newgrid, depth - 1);

		if (grid->mostvalue < newgrid->mostvalue + grid->wordlist[g]->points)
		{
			//delete grid->next;
			//grid->next = newgrid;

			grid->mostvalue = newgrid->mostvalue + grid->wordlist[g]->points;
			bestword = g;
		}
		
		delete newgrid;
	}

	return bestword;
}


int ThingSolve(Grid * grid)
{
	//Grid * newgrid = grid;
	int allpoints = 0;

	while(1)
	{
		int g = SolverThing(grid, 0);

		if (g < 0)
		{
			if (grid->grid[COLS-1][ROWS-1] == 0)
			{
				allpoints += 500;
			}

			return allpoints;
		}

		int points = 0;
		for (int b=0;b<grid->wordlist[g]->length;b++)
			points += GetPoints(grid->wordlist[g]->word[b].letter);

		allpoints += points * (grid->wordlist[g]->length);

		//allpoints += grid->mostvalue;

		grid->ApplyWord(grid->wordlist[g]->word, grid->wordlist[g]->length);
		grid->FallGrid();

		for (int g=0;g<(int)grid->wordlist.size();g++)
			delete grid->wordlist[g];
		
		grid->wordlist.clear();

		pSolve->nummoves++;
	}
}


void SolveFromBottom(Grid * in)
{
	if (in->next)
	{
		SolveFromBottom(in->next);

		//printf("Solving:\n");
		//in->PrintGrid();

		in->pCallBack = SolveTest;
		in->FindWords();
	}
}

void FindBest(Grid * grid)
{
	Grid * newgrid = 0;
	grid->pCallBack = BestScores;	
	grid->FindWords();
	grid->mostvalue = 0;

	if (!grid->words)
	{
		grid->next = 0;

		if (grid->grid[COLS-1][ROWS-1] == 0)
			grid->mostvalue = 500;

		return;
	}

	for (int g=(int)grid->wordlist.size()-1;g>=0;g--)
	{
		newgrid = new Grid(grid);
		newgrid->ApplyWord(grid->wordlist[g]->word, grid->wordlist[g]->length);
		newgrid->FallGrid();

		if (!grid->next)
			grid->next = newgrid;

		FindBest(newgrid);

		if (grid->mostvalue < newgrid->mostvalue + grid->wordlist[g]->points)
		{
			if (grid->next != newgrid)
				delete grid->next;

			grid->next = newgrid;
			grid->mostvalue = newgrid->mostvalue + grid->wordlist[g]->points;
		}
		else {
			newgrid->~Grid();
			delete newgrid;
		}
	}

}

unsigned int SolveThread(void * input)
{
	Solver * solve = (Solver*)input;
	Grid * grid = solve->start;
	

	FindBest(grid);

	/*Grid * newgrid;
	while (1) {
		grid->pCallBack = BestScores;	
		grid->FindWords();

		if (!grid->words)
		{
			grid->next = 0;
			//if (grid->grid[COLS-1][ROWS-1] == 0) allpoints += 500;
			break;
		}

		newgrid = new Grid(grid);

		//newgrid->ApplyWord(grid->word, grid->wordlen);
		newgrid->ApplyWord(grid->wordlist[grid->wordlist.size()-1]->word, grid->wordlist[grid->wordlist.size()-1]->length);
		newgrid->FallGrid();

		grid->next = newgrid;

		grid = newgrid;
	}*/



	//SolveFromBottom(solve->start);

	//std::vector<Grid*>::iterator iter = solve->moves.end();
	
	/*while (1)
	{
		grid = solve->moves.back();

		if (iter == solve->moves.begin()) {
			printf("Solver finished.\n");
			return 0;
		}
		if ((*iter)->words == 0) iter--;

		(*iter)->pCallBack = SolveTree;
		//(*iter)->FindWords();
	}*/

	return 0;
}

void Solver::PopWord()
{
	Grid * ptr = start;

	int move = 0;
	Grid * del;//= in->next;

	while (ptr)
	{
		del = ptr;
		ptr = del->next;

		printf("Grid: %d\n", move++);

		int points = 0;
		printf("Word: ");
		for (int b=0;b<del->wordlen;b++)
		{
			points += GetPoints(del->word[b].letter);
			//printf("%c %d,%d\n", grid->word[b].letter, grid->word[b].x, grid->word[b].y);
			printf("%c", del->word[b].letter);
		}
		printf(" (%d)\n", points * (del->wordlen));
		printf("Value: %d Words: %d\n", del->mostvalue, del->words);
	}


/*if (nummoves >= (int)moves.size())
	{
		printf("No word to pop...\n");
		return;
	}

	Grid * grid = moves[nummoves];

	int points = 0;
	printf("Word: \n");
	for (int b=0;b<grid->wordlen;b++)
	{
		points += GetPoints(grid->word[b].letter);
		//printf("%c %d,%d\n", grid->word[b].letter, grid->word[b].x, grid->word[b].y);
		printf("%c", grid->word[b].letter);
	}
	printf(" (%d)\n", points * (grid->wordlen));

	allpoints += points * (grid->wordlen);

	printf("Points: %d Value: %d Words: %d\n", allpoints, grid->mostvalue, grid->words);

	grid->PrintGrid();

	//grid->ApplyWord(grid->word, grid->wordlen);
	//grid->FallGrid();

	nummoves++;*/
}

/*

	grid->words = 9999999;
	grid->pCallBack = BestScore;

	while(1)
	{
		if (grid->words < 600)
		{
			grid->pCallBack = VRecurse;
		}

		grid->FindWords();

		if (!grid->words)
		{
			//grid->PrintGrid();
			if (grid->grid[COLS-1][ROWS-1] == 0) allpoints += 500;
			printf("No More Words: %d\n", allpoints);
			break;
		}

		//system("pause");

		int points = 0;
		printf("Word: \n");
		for (int b=0;b<grid->wordlen;b++)
		{
			points += GetPoints(grid->word[b].letter);
			//printf("%c %d,%d\n", grid->word[b].letter, grid->word[b].x, grid->word[b].y);
			printf("%c", grid->word[b].letter);
		}
		printf(" (%d)\n", points * (grid->wordlen));

		allpoints += points * (grid->wordlen);

		printf("Points: %d Value: %d Words: %d\n", allpoints, grid->mostvalue, grid->words);

		grid->PrintGrid();

		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();
	}

}*/

int SolveDepth(Grid * grid, int depth)
{
	grid->pCallBack = (CallBack)BestScore;

	int allpoints = 0;

	while(depth > 0)
	{
		depth--;
		
		if (grid->grid[COLS-1][ROWS-1] == 0)
		{
			allpoints += 10000;
			return allpoints;
		}

		grid->FindWords();

		if (!grid->words)
		{
			return allpoints;
		}

		int points = 0;
		for (int b=0;b<grid->wordlen;b++)
			points += GetPoints(grid->word[b].letter);

		allpoints += points * (grid->wordlen);

		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();
	}

	return allpoints;
}

#define VOWEL -1
#define CONSONANT 4


	//int letcount[26] = {VOWEL,CONSONANT,CONSONANT,CONSONANT,VOWEL,CONSONANT,CONSONANT,CONSONANT,VOWEL,CONSONANT,CONSONANT,CONSONANT,CONSONANT,CONSONANT,VOWEL,CONSONANT,CONSONANT,CONSONANT,CONSONANT,CONSONANT,VOWEL,CONSONANT,CONSONANT,CONSONANT,CONSONANT,CONSONANT};
	//{ 1, 4, 3, 2, 1, 5, 3, 4, 2, 8, 5, 3, 4, 2, 1, 3, 10, 2, 1, 1, 3, 5, 4, 8, 4, 10 };
	

int letvalue[26] =		{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int recletvalue[26] =	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void GetRatio(Grid * in)
{
	int x,y;
	int theletcount[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

	in->numletters = 0;

	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (in->grid[x][y] < 'A' || in->grid[x][y] > 'Z') continue;

		theletcount[in->grid[x][y] - 'A']++;
		in->numletters++;
	}

	if (!in->numletters) return;

	for (int l=0;l<26;l++)
	{
		 int want = (int)(Dictionary->letprob[l] * in->numletters); //- ((double)letcount[l] / (double)numletters);

		 letvalue[l] = theletcount[l] - want;	
	}

	/*if (letcount['Q' - 'A'] && letcount['Q' - 'A'] + 1 >= letcount['U' - 'A'])
	{
		letcount['Q' - 'A'] += 500;
		letcount['U' - 'A'] -= 400;
	}*/
}



void GetRecRatio(Grid * in)
{
	int x,y;
	
	int letcount[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

	in->numletters = 0;

	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (in->grid[x][y] < 'A' || in->grid[x][y] > 'Z') continue;

		letcount[in->grid[x][y] - 'A']++;
		in->numletters++;
	}

	if (!in->numletters) return;

	for (int l=0;l<26;l++)
	{
		 int want = (int)(Dictionary->letprob[l] * in->numletters); //- ((double)letcount[l] / (double)numletters);

		 recletvalue[l] = letcount[l] - want;	
	}

	/*if (letcount['Q' - 'A'] && letcount['Q' - 'A'] + 1 >= letcount['U' - 'A'])
	{
		recletcount['Q' - 'A'] += 500;
		recletcount['U' - 'A'] -= 400;
	}*/
}

int finalgrids = 0;
int finalletters = 0;
int finalcount[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

void Start()
{
	if (!finalgrids) finalgrids = 1;

	for (int l=0;l<26;l++)
	{
		letvalue[l] = (finalcount[l] / finalgrids);
	}

	//finalgrids;
	finalletters = 0;
	
	for (int l=0;l<26;l++)
	{
		finalcount[l] = 0;
	}
}

void BoostValue(Grid * in)
{
	int x,y;
	//int letcount[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

	finalgrids++;

	for (y=0;y<ROWS;y++)
	for (x=0;x<COLS;x++)
	{
		if (in->grid[x][y] < 'A' || in->grid[x][y] > 'Z') continue;

		finalcount[in->grid[x][y] - 'A']++;
		finalletters++;
	}

	//if (letter >= 'A' && letter <= 'Z') return valuearray[letter - 'A'];
}

void BestScoreShape(Grid * in)
{
	int tail = 0;
	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		points += GetPoints(in->current[c].letter);

		if (in->current[c].y == ROWS - 1)
		{ 
			if (!in->grid[in->current[c].y-1][in->current[c].x]) tail += 1;
			//if (in->current[c].x && !in->grid[in->current[c].y][in->current[c].x-1]) tail += 1;
		}
	}

	points *= (in->length);
	
	points += pSolve->gtailmult*tail;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		for (int c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}

void BestValue(Grid * in)
{
	int tail = 0;
	int ratio = 0;
	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		ratio += letvalue[in->current[c].letter - 'A'];

		points += GetPoints(in->current[c].letter);

		if (in->current[c].y == ROWS - 1 && !in->grid[in->current[c].y-1][in->current[c].x])
		{
			tail += 1;
			
			//if (in->current[c].x && !in->grid[in->current[c].y][in->current[c].x-1]) tail += pSolve->ltailmult;
		}
	}

	points *= in->length;

	points += pSolve->ratiomult*ratio;
	points += pSolve->gtailmult*tail / 2;

	/*if (newgrid->grid[COLS-1][ROWS-1])
	{
		points += (int)(pSolve->shapemult*newgrid->Shape());
		points += pSolve->gtailmult*(pSolve->tail - newgrid->GetTail());
		
		points += pSolve->ratiomult*ratio;
		//if (pSolve->ratiomult)	points -= (int)((float)pSolve->ratiomult * newgrid->Ratio());
	}
	else points += 500;

	delete newgrid;*/

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		for (int c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}


int ValueRecurse(Grid * grid)
{
	int allpoints = 0;
	int nummoves = 0;

	grid->words = 9999999;
	grid->pCallBack = BestValue;

	while(1)
	{
		if (grid->words < pSolve->variable)
		{
			GetRecRatio(grid);
			grid->pCallBack = VRecurse;
		}
		else
		{
			GetRatio(grid);
			grid->pCallBack = BestValue;
		}

		grid->FindWords();

		if (!grid->words)
		{
			if (grid->grid[COLS-1][ROWS-1] == 0) allpoints += 500;

			break;
		}

		//system("pause");

		int points = 0;
		//printf("Word: \n");
		for (int b=0;b<grid->wordlen;b++)
		{
			points += GetPoints(grid->word[b].letter);
			//printf("%c %d,%d\n", grid->word[b].letter, grid->word[b].x, grid->word[b].y);
			//printf("%c", grid->word[b].letter);
		}
		//printf(" (%d)\n", points * (grid->wordlen));

		if (pSolve->pDraw)
			(*pSolve->pDraw)(grid);

		allpoints += points * (grid->wordlen);

		//printf("Points: %d Value: %d Words: %d\n", allpoints, grid->mostvalue, grid->words);
		//grid->PrintGrid();

		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();

		nummoves++;
	}

	return allpoints;
}


int ValueSolve(Grid * grid)
{
	grid->pCallBack = (CallBack)BestValue;

	int allpoints = 0;

	while(1)
	{
		//printf("Shape: %f, Ratio %f\n", grid->Shape(), grid->Ratio());

		if (grid->grid[COLS-1][ROWS-1] == 0)
		{
			allpoints += 500;
			//printf("Score %d, Words; %d, Finished!!!!!!!!\n", allpoints, pSolve->words);
			return allpoints;
		}

		GetRatio(grid);
		grid->FindWords();

		if (!grid->words)
		{
			return allpoints;
		}

		int points = 0;
		for (int b=0;b<grid->wordlen;b++)
			points += GetPoints(grid->word[b].letter);

		allpoints += points * (grid->wordlen);
		//allpoints += grid->mostvalue;

		grid->ApplyWord(grid->word, grid->wordlen);
		grid->FallGrid();
		
		pSolve->nummoves++;
	}
}

void VRecurse(Grid * in)
{
	Grid * newgrid = new Grid(in);

	int tail = 0;
	int ratio = 0;
	int points = 0;
	for (int c=0;c<in->length;c++)
	{
		ratio += recletvalue[in->current[c].letter - 'A'];

		points += GetPoints(in->current[c].letter);

		if (in->current[c].y == ROWS - 1 && !in->grid[in->current[c].y-1][in->current[c].x])
		{
			tail += 1;
			
			//if (in->current[c].x && !in->grid[in->current[c].y][in->current[c].x-1]) tail += pSolve->ltailmult;
		}
	}

	points *= in->length;
	points += pSolve->ratiomult*ratio;
	points += pSolve->gtailmult*tail / 2;

	newgrid->ApplyWord(in->current, in->length);
	newgrid->FallGrid();
	
	points += ValueSolve(newgrid);

	delete newgrid;

	if (points > in->mostvalue)
	{
		in->mostvalue = points;

		int c=0;
		for (c=0;c<in->length;c++)
		{
			in->word[c].letter = in->current[c].letter;
			in->word[c].x = in->current[c].x;
			in->word[c].y = in->current[c].y;
		}

		in->wordlen = in->length;
	}
}


void Solver::Solve(Grid * grid)
{
	allpoints = 0;
	nummoves = 0;
	runtime = 0;
	letters = 0;

	allpoints = ValueRecurse(grid); //ValueSolve(grid); ValueRecurse ; ThingSolve

	printf("Solved for %d\n", allpoints);
}

/*
UOIIESLNEJSWTAVHPPTEZKTOOANASAORFMIRAILOCLBTIEMBTIAEOYVNIJUDDPAERUNPJOTBBEEJSREZWMURWLTEIRABGOITNBNWLRUASIETDIHEDFAIO
AOPSMRECACIAYHFWSMLRDFIHAROBYITAIEDSDSATSNNJWTICUIEASNEUTZUARARENSSAGEQCIAQAITOAIAJBNVRWUBXPTUJOADOFCZAPIDLNEOSTMEVLG
           SZ          YOA   UUTATOYDHQ   LOGAUOLIOR  HRSIAZSITTR  VIIGDBLEALU  LUEIYROCPNZ  FAEAIUHOICL BVOCOJQBQAYM




toseaasnattsbdtfaulrbdjecvagaetmrdofrelapveokrithfspnocunokozdakbyuaernumkteiaytoslsoacsosuasfesraiareiatprtvrselxrhi
ksryaexlpnncaoqbruydnqyzuannoysedorlnacvuoauasgeccoupekxeihalphrpvedywnsyshxotatlcziningtwsettbaoeushortececarboeooml
nileiwniieolcsanuetfeawpenxanhrutpupioznupisuetqopadeepdtllnoiuzpnrsgoaaurmaoidwybaaximesmabpnomrnttodwsituawzteisias
wnaananoofnstrblijivksnenirtwtdsianbladxquevsnotlvmtaimmymuaotzokptstciytxwteetpipureowaeacrdisuusoaiosthipuseonupysr
ntqualyooginolttiowaokutteoojrpnwivrmooseobasqbpetsiizpssmpbreoreaavfodiiyrllftosowmmiieeagxirrlvtoisaitioscosacrlvnl
uegtsaevcinpotnyislzmidiwweangvuetghlagnrsityrictyrifebttprsoedsynlbnntsokrgbbceifallnrawiiiuozbsiamnrrfeutcsipgpiaed
xuzucoetekesrnsswceaxvnvleaiispimbnohuynwbdsxbdnotaaecrcoaaqtaclsqsbkdpaytamoiobthnikrawoavsuoommdianogptttsnpuyqyeoo
ilwrnvagiseeibuueelioiouetrilnaetiaovraicqcohgiixdinjssmosansvleoyahavngiqcifisegjsscmekuibtdfqibertmstineixeuymfivxo







*/
